#include "Sock.hpp"
#include <sys/select.h>
#include <sys/time.h>
#include<unistd.h>

static const uint16_t defaultport = 8080;
static const int fd_num_max = 1024;
int defaultfd = -1;

class selectserver
{
public:
    selectserver()
    {
        for (int i = 0; i < fd_num_max; i++)
        {
            fd_array[i] = defaultfd;
        }
    }
    ~selectserver()
    {
    }

    bool init()
    {
        sock.Socket();
        std::cout<<"socket succuse"<<std::endl;
        sock.Bind(defaultport);
        sock.Listen();
        return true;
    }

    void Recver(int fd, int pos)
    {
        // demo
        char buffer[1024];
        ssize_t n = read(fd, buffer, sizeof(buffer) - 1); // bug?
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << "get a messge: " << buffer << std::endl;
        }
        else if (n == 0)
        {
            close(fd);
            fd_array[pos] = defaultfd; 
        }
        else
        {
            close(fd);
            fd_array[pos] = defaultfd;
        }
    }

    //链接管理器
    void Accepter()
    {
        std::string client_ip;
        uint16_t client_port;
        int n=sock.Accept(&client_ip,&client_port);
        if (n< 0) return;

        int pos = 1;
        for (; pos < fd_num_max; pos++) // 第三个循环
        {
            if (fd_array[pos] != defaultfd)
                continue;
            else
                break;
        }
        if (pos == fd_num_max)
        {
            close(n);
        }
        else
        {
            fd_array[pos] = n;
        }
    }

    void Dispatcher(fd_set rfds)
    {
        for(int i=0;i<fd_num_max;i++)    //第二次循环
        {
            int fd=fd_array[i];
            if(fd==defaultfd) continue;
            if(FD_ISSET(fd,&rfds))
            {
                if(fd==sock.Fd())
                {
                    Accepter();
                }
                else
                {
                    Recver(fd, i);
                }
            }
        }
    }

    void start()
    {
        int Listen_Sock = sock.Fd();
        fd_array[0] = Listen_Sock;
        while (true)
        {
            fd_set rfds;
            FD_ZERO(&rfds);

            int maxfd = fd_array[0];
            for (int i = 0; i < fd_num_max; i++) //第一次循环
            {
                if (fd_array[i] == defaultfd)
                    continue;
                FD_SET(fd_array[i], &rfds);
                if (fd_array[i] > maxfd)
                {
                    maxfd = fd_array[i];
                }
            }
            struct timeval timeout = {5, 0};

            int n = select(maxfd+1, &rfds, nullptr, nullptr, &timeout);
             switch (n)
            {
            case 0:
                std::cout << "time out, timeout: " << timeout.tv_sec << "." << timeout.tv_usec << std::endl;
                break;
            case -1:
                std::cerr << "select error" << std::endl;
                break;
            default:
                std::cout << "get a new link!!!!!" << std::endl;
                Dispatcher(rfds); 
                break;
            }
        }
    }

private:
    Sock sock;
    int fd_array[fd_num_max];
};